<?php

namespace JsonLowCode\Form\Abstract;

use Closure;
use JsonLowCode\Traits\Props\HasModel;
use JsonSerializable;
use JsonLowCode\Schema;
use JsonLowCode\UI\FormField;
use JsonLowCode\Form;
use JsonLowCode\Form\Rule;
use JsonLowCode\Support\Js;

/**
 *
 */
abstract class FieldAbstract implements JsonSerializable
{
    protected Form $form;
    protected string $field;
    protected mixed $label;
    protected mixed $defaultValue = null;
    protected mixed $rule = null;
    protected ?FormField $formField = null;
    protected string|array $bindField = "";
    protected ?Schema $element = null;
    protected string|null $placeholder = null;
    protected bool $noItem = false;

    use Form\Traits\HasBooted;
    use Form\Traits\HasCommon;

    /**
     * @param string|array $field
     * @param mixed $label
     * @param Form $form
     */
    public function __construct(Form $form, string|array $field, mixed $label = null)
    {
        $this->field = $field;
        $this->label = $label;
        $this->form = $form;
        $bindKey = $this->form->getBindKey();
        if (is_string($field)){
            $this->bindField = Js::this($bindKey.".".$this->field);
        }else{
            $this->bindField = array_map(function ($item) use ($bindKey) {
                return Js::this($bindKey.".".$item);
            },$field);
        }
        $this->noItem = $this->form->getNoItem();
        if ($this->noItem){
            $this->formField = null;
        }else{
            $this->formField = new FormField($label);
        }

        $this->booting();
        $this->setBindValue();
        $this->defaultValue();
        $this->booted();
    }

    /**
     * @return $this
     */
    protected function setBindValue(): static
    {
        $this->element->bind("v-model:value",$this->bindField);
        return $this;
    }

    /**
     * @return $this
     */
    public function showLabel(bool|string $bool = true): static
    {
        $this->formField->showLabel($bool);
        return $this;
    }

    /**
     * @return $this
     */
    public function hideLabel(bool|string $bool = false): static
    {
        $this->formField->showLabel($bool);
        return $this;
    }

    /**
     * @return $this
     */
    public function setNoItem(): static
    {
        $this->formField = null;
        return $this;
    }

    /**
     * 设置默认值
     * @param mixed $value
     * @return $this
     */
    public function defaultValue(mixed $value = null): static
    {
        $this->defaultValue = $value;
        $this->form->setFieldValue($this->field, $this->defaultValue);
        $this->element->prop("defaultValue",$this->defaultValue);
        return $this;
    }

    /**
     * 帮助提示信息
     * @param string|Schema $help
     * @param string|null $helpColor 帮助提示颜色信息
     * @param bool $vertical 帮助提示信息 是否垂直布局
     * @return $this
     */
    public function help(string|Schema $help,string $helpColor = null,bool $vertical = false): static
    {
        $this->formField->help($help);
        !is_null($helpColor)&&$this->formField->helpColor($helpColor);
        $this->formField->vertical($vertical);
        return $this;
    }


    /**
     * 设置FormField
     * @param Closure|null $closure
     * @return $this
     */
    public function formField(Closure $closure = null): static
    {
        !is_null($closure)&&$closure($this->formField);
        return $this;
    }

    /**
     * 设置required
     * @param string|null $message
     * @return $this
     */
    public function required(string $message = null): static
    {
        $this->formField->path($this->field);
        $rule = new Form\Rule();
        if ($message){
            $rule->required($message);
        }else{
            if ($this->placeholder){
                $rule->required($this->placeholder);
            }
        }
        $this->rule($rule);
        return $this;
    }

    /**
     * 设置rule验证规则
     * @param array|Rule|Closure $closure
     * @return $this
     */
    public function rule(array|Form\Rule|Closure $closure): static
    {
        $this->formField->path($this->field);
        if ($closure instanceof Closure){
            $rule = new Form\Rule();
            call_user_func($closure, $rule);
            $this->form->rule($this->field,$rule);
        }else{
            $this->form->rule($this->field,$closure);
        }
        return $this;
    }

    /**
     * 设置rule 正则规则
     * @param string $pattern
     * @param string $message
     * @return $this
     */
    public function pattern(string $pattern = "", string $message = "密码不正确"): static
    {
        $rule = new Form\Rule();
        $rule->pattern($pattern)->message($message)->trigger(['input']);
        return $this->rule($rule);
    }

    /**
     * 设置FormField
     * @param Closure|null $closure
     * @return $this
     */
    public function element(Closure $closure = null): static
    {
        !is_null($closure)&&call_user_func($closure, $this->element);
        return $this;
    }


    /**
     * @return array
     */
    public function getFieldParams(): array
    {
        return [
            $this->field => JSExpression($this->bindField)
        ];
    }


    /**
     * @return array
     */
    public function jsonSerialize(): array
    {
        $this->render();
        if ($this->formField instanceof FormField){
            $this->formField->children($this->element);
            return $this->formField->jsonSerialize();
        }else{
            return $this->element->jsonSerialize();
        }
    }
}
